package com.ds.lens.data.controller;

import com.google.common.collect.Lists;
import com.ds.lens.data.common.asserts.Asserts;
import com.ds.lens.data.common.constant.Constants;
import com.ds.lens.data.service.LensApplicationService;
import com.ds.lens.data.vo.BaseOutVO;
import com.ds.lens.data.vo.enums.DataCommonVOMessageEnum;
import com.ds.lens.data.vo.factory.VOFactory;
import com.ds.lens.data.vo.in.PagedConditionInVO;
import com.ds.lens.data.vo.in.User;
import com.ds.lens.data.vo.in.v2.application.LensApplicationInVO;
import com.ds.lens.data.vo.in.v2.application.LensApplicationSearchVO;
import com.ds.lens.data.vo.in.v2.application.LensApplicationUserRelationInVO;
import com.ds.lens.data.vo.in.v2.application.UserNameSearchInVO;
import com.ds.lens.data.vo.out.PageResult;
import com.ds.lens.data.vo.out.v2.application.LensApplicationVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description:
 *
 * @author WeiShaoying
 * @date 2019-11-05
 */
@Slf4j
@RestController
@Api(value = "Lens application controller")
@RequestMapping(produces = {"application/json;charset=UTF-8"})
public class LensApplicationController {

    @Autowired
    LensApplicationService lensApplicationService;

    /**
     * Paging for query applications
     *
     * @param inVO conditions
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Paging for query applications")
    @PostMapping(value = "/lens/applications")
    public BaseOutVO getLensApplications(@RequestBody @Valid PagedConditionInVO<LensApplicationSearchVO> inVO,
                                         @RequestAttribute(value = "user") User user) {
        if (null != user && !user.isAdmin()) {
            inVO.getCondition().setUserName(user.getUsername());
        }
        PageResult<LensApplicationVO> vo = lensApplicationService.findLensApplicationByPage(inVO);
        if (null != vo) {
            return VOFactory.getSuccessBaseOutVO(vo);
        }
        return VOFactory.getBaseOutVO(DataCommonVOMessageEnum.COMMON_FAILED.getCode(), DataCommonVOMessageEnum.COMMON_FAILED.getMessage());
    }

    /**
     * Save application
     *
     * @param inVO inVO
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Save application")
    @PostMapping(value = "/lens/application")
    public BaseOutVO saveLensApplication(@RequestBody @Valid LensApplicationInVO inVO,
                                         @RequestAttribute(value = "user") User user) {
        return VOFactory.getSuccessBaseOutVO(lensApplicationService.saveLensApplication(inVO, user));
    }

    /**
     * Query users from base info API
     *
     * @param inVO
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Query users from base info API")
    @PostMapping(value = "/lens/baseinfo/users")
    public BaseOutVO getBaseInfoUsers(@RequestBody @Valid UserNameSearchInVO inVO) {
        Asserts.assertNotNull(inVO, Constants.ErrorCode.PARAM_ERROR, "Param can not be empty.");
        Asserts.assertNotEmpty(inVO.getParam(), Constants.ErrorCode.PARAM_ERROR, "Param can not be empty.");
        if (null != inVO.getUserType() && inVO.getUserType() == Constants.UserTypeEnum.SSO.getCode()) {
            return VOFactory.getSuccessBaseOutVO(lensApplicationService.findBaseInfoUsers(inVO.getParam()));
        } else {
            //TODO 实现本地用户检索
            return VOFactory.getSuccessBaseOutVO(Collections.emptyList());
        }
    }


    /**
     * Save the relationship between users and applications
     * 添加成员
     *
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Save the relationship between users and applications")
    @PostMapping(value = "/lens/user/application/relation")
    public BaseOutVO saveUserApplicationRelation(@RequestBody @Valid LensApplicationUserRelationInVO inVO,
                                                 @RequestAttribute(value = "user") User user) {
        Asserts.assertNotNull(inVO, Constants.ErrorCode.PARAM_ERROR, "Parameter can not be null.");
        int userType = Constants.UserTypeEnum.SSO.getCode();
        if (null != inVO) {
            userType = inVO.getUserType();
        }
        return VOFactory.getSuccessBaseOutVO(lensApplicationService.saveApplicationUserRelation(inVO.getApplicationId(), inVO.getUserName(), inVO.getApplicationRole(), userType, user));
    }

    /**
     * Query application users
     *
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Query application users")
    @GetMapping(value = "/lens/application/users")
    public BaseOutVO queryApplicationUsers(@RequestParam("applicationId") long applicationId) {

        return VOFactory.getSuccessBaseOutVO(lensApplicationService.findAppUsersByAppId(applicationId));
    }

    /**
     * Delete application user
     *
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Delete application user")
    @GetMapping(value = "/lens/application/user/delete")
    public BaseOutVO deleteApplicationUser(@RequestParam("id") long relationId,
                                           @RequestAttribute(value = "user") User user) {
        lensApplicationService.deleteAppUserByRelationId(relationId, user);
        return VOFactory.getSuccessBaseOutVO();
    }

    /**
     * Query application roles
     *
     * @return BaseOutVO object
     */
    @ApiOperation(value = "Query application roles")
    @GetMapping(value = "/lens/application/roles")
    public BaseOutVO queryApplicationRoles(@RequestAttribute(value = "user") User user) {
        List<Map<String, String>> result = Lists.newArrayListWithCapacity(2);
        if (user.isAdmin()) {
            for (Constants.ApplicationRoleEnum roleEnum : Constants.ApplicationRoleEnum.values()) {
                Map<String, String> map = new HashMap<>();
                map.put("key", String.valueOf(roleEnum.getCode()));
                map.put("value", roleEnum.getName());
                result.add(map);
            }
        } else {
            Map<String, String> map = new HashMap<>(2);
            map.put("key", String.valueOf(Constants.ApplicationRoleEnum.APPLICATION_USER.getCode()));
            map.put("value", Constants.ApplicationRoleEnum.APPLICATION_USER.getName());
            result.add(map);
        }

        return VOFactory.getSuccessBaseOutVO(result);
    }
}
